/*
 * WaveDisplay.java
 *
 * Copyright (c) 2010 Jaymie Strecker (strecker at cs.umd.edu). All rights reserved.
 *
 * This file is part of Tonic.
 *
 * Tonic is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Tonic is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Tonic.  If not, see <http://www.gnu.org/licenses/>.
 */

package tonic.gui;

import java.awt.event.AdjustmentEvent;
import javax.swing.*;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.AdjustmentListener;
import tonic.audio.Player;

/**
 *
 * @author Jaymie Strecker (strecker at cs.umd.edu)
 */
public class WaveDisplay extends JPanel implements AdjustmentListener {

    private static final int DEFAULT_VIEW_SECONDS = 5;
    private JScrollPane scrollPane;
    private WaveCanvas canvas;
    private JPanel leftMargin;
    private JPanel rightMargin;
    private JPanel viewPanel;
    private JFrame parent;
    private ChordDisplay chordDisplay;
    private volatile boolean isPlaying;

    public WaveDisplay(JFrame parent, ChordDisplay chordDisplay) {
        super();
        this.parent = parent;
        this.chordDisplay = chordDisplay; 
        isPlaying = false;
        scrollPane = new JScrollPane();
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
        scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
        initContents(); 
        setLayout(new FlowLayout(FlowLayout.LEFT));
        add(scrollPane);
        scrollPane.getHorizontalScrollBar().addAdjustmentListener(this);
    }

    private void initContents() {
        leftMargin = new JPanel();
        canvas = new WaveCanvas(chordDisplay);
        rightMargin = new JPanel();
        int canvasHeight = (int) canvas.getPreferredSize().getHeight();
        int viewWidth;
        if (Player.getFile() == null) {
            viewWidth = 0;
        } else {
            canvas.resetPlayer();
            viewWidth = canvas.getViewWidth(DEFAULT_VIEW_SECONDS);
            leftMargin.setPreferredSize(new Dimension(viewWidth / 2, canvasHeight));
            rightMargin.setPreferredSize(new Dimension(viewWidth / 2, canvasHeight));
            // TODO - allow display to resize when window resizes
        }
        viewPanel = new JPanel();
        viewPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
        viewPanel.add(leftMargin);
        viewPanel.add(canvas);
        viewPanel.add(rightMargin);
        scrollPane.setViewportView(viewPanel);
        scrollPane.setPreferredSize(new Dimension(viewWidth, canvasHeight + 20));
        parent.pack();
    }

    public void resetPlayer() {
        initContents();
    }

    public void play() {
        isPlaying = true;
        canvas.setIsPlaying(true);
        new Thread(new PlayPositionUpdater()).start();
    }

    public void pause() {
        isPlaying = false;
        canvas.setIsPlaying(false);
    }

    private class PlayPositionUpdater implements Runnable {

        public void run() {
            while (isPlaying) {
                int playPositionSample = Player.getSamplePosition();
                float playPositionPercent = playPositionSample / (float) Player.getNumSamples();
                canvas.setPlayPosition(playPositionPercent);

                BoundedRangeModel m = scrollPane.getHorizontalScrollBar().getModel();
                float maxScroll = m.getMaximum() - m.getExtent();
                int playPositionScroll = Math.round(playPositionPercent * maxScroll);
                m.setValue(playPositionScroll);

                try {
                    Thread.sleep(20);
                } catch (InterruptedException e) {
                    // nop
                }
            }
        }

    }

    // Listener for scrollbar
    public synchronized void adjustmentValueChanged(AdjustmentEvent e) {
        if (! isPlaying && Player.getFile() != null) {
            BoundedRangeModel m = scrollPane.getHorizontalScrollBar().getModel();
            float maxScroll = m.getMaximum() - m.getExtent();
            float playPositionPercent = m.getValue() / maxScroll;
            int playPositionSample = Math.round(playPositionPercent * Player.getNumSamples());
            canvas.setPlayPosition(playPositionPercent);
            try {
                Player.setSamplePosition(playPositionSample);
            } catch (Exception ex) {
                new ErrorDisplay(this, "There was a problem updating the player's position.", ex);
            }
        }
    }
}
